#ifndef MATRIX_H
#define MATRIX_H

#include "../include/Vector.h"
#include <iostream>

class Matrix
{
    int nRows;
    int nColumns;

    real **data;

    public:
        Matrix(int r = 1, int c = 1);
        Matrix(const Matrix& m);
        Matrix(const Vector& m);

        virtual ~Matrix();

        const real          operator() (int , int )const;
        real&               operator() (int , int );
        const real          at(int , int )const;
        real&               at(int , int );
        void        setRow    (int , const Vector& );
        void        setColumn (int , const Vector& );
        void        setVector (int , const Vector& );
        Matrix                operator+  (const Matrix&)const;
        Matrix                operator-  (const Matrix&)const;
        Matrix                operator-  ()              const;
        Matrix                operator*  (real a)const;
        friend Matrix        operator*  (real a,const Matrix& );
        const Matrix&        operator=  (const Matrix& );
        Matrix                operator*  (const Matrix&)const;
        Vector                operator*  (const Vector &)const;
        friend Vector        operator*  (const Vector &,const Matrix& );
        void loadIdentity();


        const int rows()const;
        const int columns()const;

        Vector row(int )const;
        Vector column(int )const;

        void swapLines(int lineA, int lineB);

        friend std::ostream& operator<<(std::ostream& out, const Matrix& m);

        void set(real * d);
        void set(real **d);
        Matrix transpose()const;
        void LU_Decomposition(Matrix& L, Matrix& U);
        Matrix choleskyDecomposition();
        Vector solveGauss(const Vector& b);
        Vector solveGaussJacob(const Vector& b);
        Vector solveGaussSeidel(const Vector& b);

        static Matrix rotation(int n, int i, int j, real cos, real sen);
        void QR_Decomposition(Matrix& Q, Matrix& R);
};

#endif // MATRIX_H
